/*
 *  Copyright 2004 Blandware (http://www.blandware.com)
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package com.blandware.atleap.webapp.taglib.core.content;

import com.blandware.atleap.common.util.StringUtil;
import com.blandware.atleap.webapp.util.core.WebappUtil;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.struts.taglib.TagUtils;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.tagext.SimpleTagSupport;
import java.util.Locale;
import java.util.Map;

/**
 * <p>Searches for value in specified map containing pairs (localeIdentifier -&gt; message).
 * If <code>language</code> attribute is not specified, it is taken from session by key
 * <code>org.apache.struts.Globals.LOCALE_KEY</code>
 * </p>
 * <p>
 * While searching, following rules are applied:<br />
 * <ul>
 * <li>
 * 1. If valueMap is null or is empty, null is returned.
 * </li>
 * <li>
 * 2. Otherwise, searching through valueMap for <code>language</code>
 * </li>
 * <li>
 * 2.5 Following steps are applied only if <code>complexSearch</code> is "true"
 * </li>
 * <li>
 * 3. If nothing has been found in step 2, searching for default locale for our application
 * </li>
 * <li>
 * 4. If still not found, returning first mapping value from valueMap
 * </li>
 * </ul>
 * </p>
 * <p>
 * Allowed attributes are:
 * <ul>
 * <li>
 * <b>valueMap</b> - map of values from which some value will be taken
 * </li>
 * <li>
 * <b>language</b> - content locale identifier for which the <b>valueMap</b>
 * will be searched
 * </li>
 * <li>
 * <b>complexSearch</b> - whether to use more complex rules: if no value was
 * found for given language, search for value corresponding to default locale,
 * and if still not found, return first value from map. May be "true" or
 * "false", default is "true".
 * </li>
 * <li>
 * <b>filter</b> - whether to encode HTML-sensitive characters (like ampersand)
 * when writing result to page
 * </li>
 * <li>
 * <b>var</b> - name of scope variable to export result to. If not given, result
 * is written directly to page.
 * </li>
 * <li>
 * <b>scope</b> - scope of variable to export result to
 * </li>
 * </ul>
 * </p>
 * <p><a href="FieldValueTag.java.html"><i>View Source</i></a></p>
 *
 * @author Sergey Zubtsovskiy <a href="mailto:sergey.zubtsovskiy@blandware.com">&lt;sergey.zubtsovskiy@blandware.com&gt;</a>
 * @version $Revision: 1.14 $ $Date: 2006/08/03 10:08:14 $
 * @jsp.tag name="fieldValue"
 * body-content="empty"
 * @see org.apache.struts.Globals#LOCALE_KEY
 */
public class FieldValueTag extends SimpleTagSupport {

	protected transient final Log log = LogFactory.getLog(FieldValueTag.class);

	/**
	 * Map to get value from
	 */
	protected Map valueMap;

	/**
	 * Locale to get value for. By default it is taken from session
	 */
	protected String language;

	/**
	 * If this attribute is set to <code>true</code> and no value in map found for
	 * currently active locale, <code>null</code> will be returned, otherwise more complex
	 * search will be executed
	 */
	protected Boolean complexSearch = Boolean.TRUE;

	/**
	 * Whether or not to replace characters, which are sensitive in HTML, with their entity equivalents.<br />
	 */
	protected Boolean filter = Boolean.TRUE;

	/**
	 * Name of variable to export value
	 */
	protected String var;

	/**
	 * Scope to export variable to
	 */
	protected String scope;

	/**
     * Returns map of values
     *
	 * @return map of values
	 * @jsp.attribute required="true"
	 * rtexprvalue="true"
	 * type="java.util.Map"
	 * description="Map to get value from"
	 */
	public Map getValueMap() {
		return valueMap;
	}

    /**
     * Sets map of values
     *
     * @param valueMap map of values to set
     */
	public void setValueMap(Map valueMap) {
		this.valueMap = valueMap;
	}

	/**
     * Returns language for which to obtain value
     *
	 * @return language
	 * @jsp.attribute required="false"
	 * rtexprvalue="true"
	 * type="java.lang.String"
	 * description="Locale to get value for"
	 */
	public String getLanguage() {
		return language;
	}

    /**
     * Sets language for which to obtain value
     *
     * @param language language to set
     */
	public void setLanguage(String language) {
		this.language = language;
	}

	/**
     * Returns whether more complex search should be performed
     *
	 * @return whether more complex search should be performed
     * @see #complexSearch
	 * @jsp.attribute required="false"
	 * rtexprvalue="true"
	 * type="java.lang.Boolean"
	 * description="Whether or not to execute complex search, if none is found for currently active locale"
	 */
	public Boolean getComplexSearch() {
		return complexSearch;
	}

    /**
     * Sets whether more complex search should be performed
     *
     * @param complexSearch whether more complex search should be performed
     * @see #complexSearch
     */
	public void setComplexSearch(Boolean complexSearch) {
		this.complexSearch = complexSearch;
	}

	/**
     * Returns whether or not to replace characters, which are sensitive in
     * HTML, with their entity equivalents.
     *
	 * @return whether to replace characters, which are sensitive in HTML
	 * @jsp.attribute required="false"
	 * rtexprvalue="true"
	 * type="java.lang.Boolean"
	 * description="Whether or not to replace characters, which are sensitive in HTML, with their entity equivalents"
	 */
	public Boolean getFilter() {
		return filter;
	}

    /**
     * Sets whether or not to replace characters, which are sensitive in HTML,
     * with their entity equivalents.
     *
     * @param filter whether to replace characters, which are sensitive in HTML
     */
	public void setFilter(Boolean filter) {
		this.filter = filter;
	}

	/**
     * Returns name of variable that will accept the result
     *
     * @return name of variable
	 * @jsp.attribute required="false"
	 * rtexprvalue="true"
	 * type="java.lang.String"
	 * description="Name of variable to export message"
	 */
	public String getVar() {
		return var;
	}

    /**
     * Sets name of variable that will accept the result
     *
     * @param var name of variable to set
     */
	public void setVar(String var) {
		this.var = var;
	}

	/**
     * Returns variable scope
     *
     * @return variable scope
	 * @jsp.attribute required="false"
	 * rtexprvalue="true"
	 * type="java.lang.String"
	 * description="Scope to export variable to"
	 */
	public String getScope() {
		return scope;
	}

    /**
     * Sets variable scope
     *
     * @param scope variable scope to set
     */
	public void setScope(String scope) {
		this.scope = scope;
	}

    /**
     * Processes the tag
     *
     * @throws JspException
     */
	public void doTag() throws JspException {

		PageContext pageContext = (PageContext) getJspContext();
		HttpServletRequest request = (HttpServletRequest) pageContext.getRequest();

		if ( language == null ) {
			Locale locale = WebappUtil.getEnsuredUserLocale(request);
			if ( locale == null ) {
				locale = Locale.getDefault();
			}
			language = locale.getLanguage();
		}

		if ( complexSearch == null ) {
			complexSearch = Boolean.TRUE;
		}

		if ( filter == null ) {
			filter = Boolean.TRUE;
		}

		String fieldValue = WebappUtil.getFieldValue(valueMap, language, (HttpServletRequest) pageContext.getRequest(), complexSearch.booleanValue());

		if ( fieldValue == null ) {
			fieldValue = new String();
		}

		if ( filter.booleanValue() ) {
			fieldValue = StringUtil.htmlEncode(fieldValue);
		}

		TagUtils tagUtils = TagUtils.getInstance();
		if ( var != null ) {
			// save value in specified scope
			int varScope = PageContext.PAGE_SCOPE;
			if ( scope != null ) {
				varScope = tagUtils.getScope(scope);
			}
			pageContext.setAttribute(var, fieldValue, varScope);

		} else {
			// write message directly to page
			tagUtils.write(pageContext, fieldValue);
		}

	}

}
